STM32F407普通IO口模拟串口实现不定长数据收发 |
您所在的位置:网站首页 › stm32 模拟看门狗 下限 › STM32F407普通IO口模拟串口实现不定长数据收发 |
前言
因为项目中用到的串口比较多,STM32F407VET6自带的串口不够用了,所以只能考虑用模拟串口来实现功能。普通的IO口来模拟串口需要先了解串口的时序图,需要用到两个IO引脚即收发引脚,两个定时器,一个用于发送延时使用,一个用于产生中断接收数据。代码的初始化主要用CubeMx自动生成,功能代码自己完成。下面一起来看看吧。 目录 前言 一、普通IO模拟串口原理 二、实际应用 1.STM32CubeMx初始化 2.数据发送和接收功能代码 测试功能代码 一、普通IO模拟串口原理单片机普通io模拟串口的关键在于弄清楚串口的时序图,也是普通IO需要严格的遵循串口协议规则,串口时序图如下图所示。 一个起始位是从高电平到低电平,中间八位是数据位和奇偶校验位 ,第十位是停止位,这样就接收了一个字节的数据。 模拟串口还有最重要的一点是串口波特率,一般常见的有115200和9600,当波特率是115200时,发送1bit数据需要 1/115200 = 8.68us;所以,根据协议每一位数据传输电平持续8.68us,当波特率是9600时,发送1bit数据需要 1/9600= 104us;所以,根据协议每一位数据传输电平持续104us。 在接收的地方,通过中断来触发启动,然后启动一个定时器,根据波特率的电平持续时间,在电平的中间去检测,是高电平还是低电平,从而确定bit的值。所以,检测到下降沿后延时一下,再启动定时器,定时去判断IO的高低。 此处参考:48 STM32普通IO模拟usart串口_stm32io口模拟uart_Chasing_Chasing的博客-CSDN博客 二、实际应用 1.STM32CubeMx初始化首先是选择STM32F407VET6芯片,然后配置始终和需要的IO口和定时器 我配置的主时钟比较高,为168MHz 下面是两个定时器,定时器6是用来发送延时的,定时器7是经过104us产生中断接受数据电平的 下面配置两个普通的IO口,我配置的是PF3和PF4, PF3用来发送数据,PF4用来接收数据,PF4需要下降触发中断,下面细讲。 配置完以后记得使能相应的中断,定时器7的中断和PF4的下降沿中断。 数据发送主要是根据串口时序图进行发送相应的电平位,iousart.h代码如下: #ifndef __IOUSART_H_ #define __IOUSART_H_ #include "stm32f4xx_hal.h" #include "gpio.h" //#include "sys.h" //#include "delay.h" //定义通信波特率 #define BaudRate_9600 104 //1000000us/9600=104.1666 发送1个位所需要的时间 //GPIO TX脚宏定义 #define iouart1_TXD(n) if(n) HAL_GPIO_WritePin(GPIOF, GPIO_PIN_3, GPIO_PIN_SET); \ else HAL_GPIO_WritePin(GPIOF, GPIO_PIN_3, GPIO_PIN_RESET); //GPIO RX脚宏定义 #define iouart1_RXD() HAL_GPIO_ReadPin(GPIOF, GPIO_PIN_4) #define SUartLength 200 //模拟串口缓冲区长度 enum{ COM_START_BIT, COM_D0_BIT, COM_D1_BIT, COM_D2_BIT, COM_D3_BIT, COM_D4_BIT, COM_D5_BIT, COM_D6_BIT, COM_D7_BIT, COM_STOP_BIT, }; void iouart1_delayUs(volatile uint32_t nTime); void iouart1_delayUs_104(void); void S_Uart_Send_Buff(uint8_t *buff,uint8_t length); void S_Uart_Send_Str(uint8_t *str); void S_Uart_One_Tx(uint8_t Data); uint8_t S_Uart_Rx_Handler(uint8_t *buf,uint8_t *length); #endif /* __LED_H */ iousart.c代码如下: #include #include "iousart.h" #include "tim.h" #include "string.h" uint32_t recvData = 0; uint8_t recvStat = COM_STOP_BIT; uint8_t SUartCnt; //模拟串口缓冲区长位置 uint8_t SUartBuff[SUartLength]; uint8_t len; uint8_t buff[200]; //模拟串口缓冲区 /*************************************** * 函 数 名: Delay_Ms * 功能说明: 延时 * 形 参:nTime,单位为uS * 返 回 值: 无 ****************************************/ void iouart1_delayUs(volatile uint32_t nTime) { uint16_t tmp; tmp = __HAL_TIM_GetCounter(&htim6); //获得 TIM6 计数器的值 if(tmp + nTime = 1; } iouart1_TXD(1); //结束标志位 iouart1_delayUs(104); } //模拟串口发送数组 void S_Uart_Send_Buff(uint8_t *buff,uint8_t length) { for(uint8_t i=0; iInstance == TIM1) { HAL_IncTick(); } /* USER CODE BEGIN Callback 1 */ if(htim->Instance == htim7.Instance) { recvStat++; if(recvStat == COM_STOP_BIT)//COM_D7_BIT { //到这里接收完成一个字节数据 HAL_NVIC_EnableIRQ(EXTI4_IRQn);//开启下降沿中断 HAL_TIM_Base_Stop(&htim7);//关闭定时器 __HAL_TIM_SetCounter(&htim7,0);//定时器清零 if(SUartCnt < SUartLength) SUartBuff[SUartCnt++] = recvData; //存入缓冲区 else SUartCnt = 0; recvData =0; return; } if(iouart1_RXD()) { recvData |= (1 S_Uart_Send_Buff(buff,len); //将收到的数据发送出去 memset(buff,0x00,200); //清除缓存 } // S_Uart_One_Tx('a'); // S_Uart_Send_Buff(p_Arr1,sizeof(p_Arr1) / sizeof(p_Arr1[0])); // S_Uart_Send_Str(AT_CMD_softAP);HAL_Delay(100); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } 测试功能代码我测试使用的是正点原子的探索者开发板STM32F407ZGT6,连好线下载好程序后,打开串口助手进行不定长数据的收发测试。 下面是测试发送函数 下面是测试将接收到的数据发送回来 到这里整个模拟串口串口就结束了,希望对你有帮助,也希望共同成长,一起建设我们伟大的祖国! 源码下载:https://download.csdn.net/download/weixin_64705314/87894084?spm=1001.2014.3001.5503 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |